/*
    kevx@09/15/2011
    
    MiniWebServer http parser
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <math.h>
#include <unistd.h>
#include <time.h>
#include "http.h"
#include "server_cfg.h"

extern void handleHtml(HttpReq* req, HttpResp *httpResp);
extern void haltNow();

static char _godReq[] = "/IwillDie";


void zeroHttpReq(HttpReq* httpReq) {
    memset(httpReq, 0, sizeof(HttpReq));
}

void zeroHttpResp(HttpResp* httpResp) {
    memset(httpResp, 0, sizeof(HttpResp));
}

ssize_t renderResp(HttpResp *httpResp, char* respBuf) {
    char tmp[1024];

    memset(tmp, 0, 1024*sizeof(char));
    sprintf(tmp, RESP_STATUS, httpResp->status, httpResp->result);
    strcat(respBuf, tmp);

    memset(tmp, 0, 1024*sizeof(char));
    sprintf(tmp, RESP_DATE, httpResp->date);
    strcat(respBuf, tmp);

    strcat(respBuf, RESP_SERVER);
    strcat(respBuf, httpResp->contentType);
    strcat(respBuf, httpResp->contentLanguage);
    strcat(respBuf, RESP_HEADER_END);

    int headerSize = strlen(respBuf);
    printf("headerSize=%d\n", headerSize);
    memcpy(respBuf + headerSize, httpResp->body, httpResp->bodySize);
    return headerSize + httpResp->bodySize;

}

void mkRespDate(char* respDate) {
    time_t lt = time(NULL);
    struct tm* gmt = gmtime(&lt);
    char* gmtStr = asctime(gmt);

    for(int i = 0; i < strlen(gmtStr); i++) {
        if(gmtStr[i] == '\n') {
            gmtStr[i] = ' ';
        }
    }

    strncpy(respDate, gmtStr, 3);
    strcat(respDate, ", ");
    strcat(respDate, gmtStr + 4);
    strcat(respDate, "GMT");
}

int isStaticReq(HttpReq* req) {
    for(int i = 0; i < STATIC_RES_COUNT; i++) {
        if(strncasecmp(_$staticRes[i].ext, req->ext, 10) == 0)
            return 1;
    }
    return 0;
}

int isGodReq(HttpReq* req) {
    return !strncasecmp(_godReq, req->uri, 50);
}

ssize_t prepareResp(HttpReq* req, char* respBuf) {
    HttpResp resp;
    zeroHttpResp(&resp);

    char bodyBuf[RESP_SIZE];
    memset(bodyBuf, 0, RESP_SIZE*sizeof(char));
    resp.body = bodyBuf;
    resp.bodySize = RESP_SIZE;
    
    if(isStaticReq(req)) {
        handleHtml(req, &resp);
    } else if(isGodReq(req)) {
        haltNow();
    }

    mkRespDate(resp.date);

    return renderResp(&resp, respBuf);
}

void parseMainReq(char* mainReq, HttpReq* req) {
    char* pch = NULL;
    char  buf[REQ_MAX_BUF];
    
    ZERO_BUF(buf, REQ_MAX_BUF);
    pch = strtok (mainReq, SPACE);
    if (pch != NULL)
    {
        strncpy(req->method, pch, REQ_MAX_METHOD);
        printf ("reqMethod=%s\n", req->method);
    }

    pch = strtok (NULL, SPACE);
    if (pch != NULL)
    {
        strncpy(req->uri, pch, REQ_MAX_URI);
        printf ("reqUri=%s\n",req->uri);
    }
    
    /*in some case ext may contains dot, following code is to fix this problem*/
    sscanf(req->uri, "%*[^.]%*c%[^\?\n]", buf);
    char* currPos = buf + strlen(buf);
    while(currPos >= buf && *currPos != '.') {
        currPos--;
    }
    strncpy(req->ext, currPos + 1, REQ_MAX_EXT);
}

void parseReq(char* req, ssize_t size, char* resp, ssize_t* respSz) {
    char buf[1024];
    memset(buf, 0, 1024*sizeof(char));
    
    char* mainReqPos = strstr(req, delimiters);
    strncpy(buf, req, (size_t)(mainReqPos - req));
    
    HttpReq httpReq;
    zeroHttpReq(&httpReq);
    parseMainReq(buf, &httpReq);
    *respSz = prepareResp(&httpReq, resp);
}

